package com.spring.framework.config.value;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Map;

/**
 * 上面讲了，通过@PropertySource 引入的配置文件时，如果@Value引用的key不存在，那么默认将整个$ {key}作为值注入，或者通过XML/Spring Boot
 * 使用PropertySourcesPlaceholderConfigurer引入配置文件时，如果@Value引用的key不存在，那么直接启动抛出异常。
 * <p>
 * 实际上，我们也可以为key设置默认值，当某个属性的key在配置文件中不存在时，就使用我们指定的默认值。这种情况在不同web服务模块使用同一套后端service
 * 业务模块时非常有用。
 * <p>
 * 语法非常简单：${key:defaultValue}，如果只有“:”而不写默认值，那么表示注入空字符串，因此注意类型转换异常。defaultValue可以使用SPEL表达式，
 * 实际上这里的defaultvalue只要是字面量部分的值都可以。
 *
 * @author xuweizhi
 * @since 2020/12/15 15:19
 */
@Component
@PropertySource(value = {"classpath:config/value3.properties", "classpath:config/value.properties"})
public class ValuePropertiesDefault {

	@Value("${key:}")
	private String key;

	/**
	 * 外部文件是没有qaz这个key的，因此设置默认值，这里默认注入空字符串""
	 */
	@Value("${qaz:}")
	private String qaz;

	/**
	 * 外部文件是没有wsx这个key的，因此设置默认值，这里默认注入1
	 * 如果不写默认值，那么Spring尝试将""转换为int类型，进而会报错
	 */
	@Value("${wsx:1}")
	private int wsx;

	/**
	 * 可以默认注入
	 */
	@Value("${edc:1,2,3,4}")
	private int[] edc;

	//可以使用SPEL表达式
	/**
	 * 外部文件有key这里的属性，因此不会使用默认值
	 */
	@Value("${key:#{'abc'.concat('def')}}")
	private String concat;


	@Value("${rfv:#{'1,0,1,1'.split(',')}}")
	private double[] rfv;


	@Value("${tgb:#{{key1: 'value1', key2: 'value2', key2: 'value3'}}}")
	private Map<String, String> map;

	//………………更多功能
	@Override
	public String toString() {
		return "ValuePropertiesDefault{" +
				"key='" + key + '\'' +
				", qaz='" + qaz + '\'' +
				", wsx=" + wsx +
				", edc=" + Arrays.toString(edc) +
				", rfv=" + Arrays.toString(rfv) +
				", concat='" + concat + '\'' +
				", map=" + map +
				'}';
	}

	/**
	 * 添加一个PropertySourcesPlaceholderConfigurer，将会在启动时检查配置文件没有对应的key的情况，并且抛出异常
	 * 一定要static修饰的方法，在一开始就执行！
	 */
	@Bean
	public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
		return new PropertySourcesPlaceholderConfigurer();
	}

	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ValuePropertiesDefault.class);
		System.out.println(applicationContext.getBean(ValuePropertiesDefault.class));
	}
}
